import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import { TransformControls } from "three/examples/jsm/controls/TransformControls.js";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
import disposeObject from "./disposeObject";

const loader = new GLTFLoader();
let envTexture: THREE.Texture;

export default class App {
  scene: THREE.Scene;
  camera: THREE.PerspectiveCamera;
  renderer: THREE.WebGLRenderer;
  orbitControls: OrbitControls;
  transformControls: TransformControls;
  container: HTMLElement;
  plane: THREE.Group = new THREE.Group();

  constructor(container: HTMLElement) {
    this.container = container;
    this.scene = this.createScene();
    this.camera = this.createCamera(container);
    this.renderer = this.createRenderer(container);
    this.orbitControls = this.createOrbitControls();
    this.transformControls = this.createTransformControls();
  }

  // 创建场景
  private createScene(): THREE.Scene {
    const scene = new THREE.Scene();
    return scene;
  }

  // 创建相机
  private createCamera(container: HTMLElement): THREE.PerspectiveCamera {
    const camera = new THREE.PerspectiveCamera(
      60,
      container.clientWidth / container.clientHeight,
      0.1,
      10000
    );
    camera.position.set(0, 0, 5);
    return camera;
  }

  // 创建渲染器
  private createRenderer(container: HTMLElement): THREE.WebGLRenderer {
    const renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.autoClear = false;
    renderer.setSize(container.clientWidth, container.clientHeight);
    container.appendChild(renderer.domElement);
    return renderer;
  }

  // 创建相机控制器
  private createOrbitControls(): OrbitControls {
    return new OrbitControls(this.camera, this.renderer.domElement);
  }

  // 创建变换控制器
  private createTransformControls(): TransformControls {
    return new TransformControls(this.camera, this.renderer.domElement);
  }

  // 增加光源
  addLight() {
    const ambientLight = new THREE.AmbientLight(0xffffff, 3);
    this.scene.add(ambientLight);

    const spotlight = new THREE.SpotLight(0xffffff, 4.5);
    spotlight.position.set(0, 1500, 0);
    spotlight.angle = Math.PI * 0.2;
    spotlight.decay = 0;
    spotlight.castShadow = true;
    spotlight.shadow.camera.near = 200;
    spotlight.shadow.camera.far = 2000;
    spotlight.shadow.bias = -0.000222;
    spotlight.shadow.mapSize.width = 1024;
    spotlight.shadow.mapSize.height = 1024;
    this.scene.add(spotlight);

    const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
    directionalLight.position.set(1, 5, -1);
    this.scene.add(directionalLight);
  }

  // 添加背景（HDRI 环境贴图）
  addBackground(image: any, showSky: boolean = false) {
    const textureLoader = new THREE.TextureLoader();

    envTexture = textureLoader.load(image);

    envTexture.mapping = THREE.EquirectangularReflectionMapping;
    envTexture.colorSpace = THREE.SRGBColorSpace;

    if (showSky) {
      this.scene.background = envTexture;
    } else {
      this.scene.environment = envTexture;
    }
  }

  // 添加地板
  addPlane(
    x: number,
    y: number,
    r: number,
    type: string = "stone",
    position: THREE.Vector3 = new THREE.Vector3(0, 0, 0)
  ) {
    const loader = new THREE.TextureLoader();
    const floorGeometry = new THREE.PlaneGeometry(x, y);
    const texture = loader.load(
      `/assets/textures/textures/${type}_diff_2k.jpg`
    );
    texture.wrapS = THREE.RepeatWrapping;
    texture.wrapT = THREE.RepeatWrapping;
    texture.repeat.set(r, r);
    texture.anisotropy = 4;

    const floorMaterial = new THREE.MeshStandardMaterial({
      map: texture,
      roughness: 0.8,
      color: 0x37527d,
      metalness: 0.2,
      bumpScale: 0.0005,
    });

    const floor = new THREE.Mesh(floorGeometry, floorMaterial);
    floor.position.set(position.x, position.y - 4, position.z);
    floor.rotation.x = -Math.PI / 2; // 使地板平行于场景
    this.plane.add(floor);
    this.scene.add(this.plane);
  }

  // 处理窗口大小变化
  onWindowResize() {
    const { clientWidth, clientHeight } = this.container;
    if (this.camera) {
      this.camera.aspect = clientWidth / clientHeight;
      this.camera.updateProjectionMatrix();
      this.renderer.setSize(clientWidth, clientHeight);
    }
  }

  // 增加坐标轴辅助器
  addAxesHelper(length: number) {
    const axesHelper = new THREE.AxesHelper(length);
    this.scene.add(axesHelper);
  }

  // 设置相机的位置
  setCameraPosition(x: number, y: number, z: number) {
    this.orbitControls.object.position.set(x, y, z);
  }

  // 设置相机朝向
  setCameraOrientation(x: number, y: number, z: number) {
    this.camera.lookAt(x, y, z);
  }

  // 设置渲染器的大小
  setRendererSize(width: number, height: number) {
    this.renderer.setSize(width, height);
  }

  // 启用视角控制
  enableViewingAngleControl() {
    this.orbitControls.screenSpacePanning = false;
    this.orbitControls.enableDamping = true;
    this.orbitControls.minPolarAngle = Math.PI / 6;
    this.orbitControls.maxPolarAngle = Math.PI / 2.001;
  }

  // 启用阴影效果
  enableShadowMap() {
    this.renderer.shadowMap.enabled = true;
  }

  // 添加模型到场景
  addModel(model: string, scene: THREE.Scene | THREE.Group) {
    return new Promise((resolve, reject) => {
      loader.load(
        model,
        (gltf) => {
          const loadedModel = gltf.scene;
          scene.add(loadedModel);
          resolve(loadedModel);
        },
        undefined,
        (err) => console.error(err)
      );
    });
  }

  // 卸载资源
  dispose() {
    console.log("dispose已执行");
    disposeObject(this.scene);
    this.renderer.dispose();
    this.renderer.forceContextLoss();
  }

  // 渲染场景
  render(
    scene: THREE.Scene = this.scene,
    camera: THREE.PerspectiveCamera = this.camera
  ) {
    this.renderer.clear();
    this.renderer.render(scene, camera);
    this.renderer.clearDepth();
  }
}
